// cloud_drive_protocol.h
#pragma once

#include <cstdint>
#include <string>
#include <vector>
#include <chrono>
#include <cstring>
#include<QDebug>
#include<memory>
#include<mutex>
#include<condition_variable>
#include<chrono>
#include<QDebug>

namespace CloudDrive {

struct UploadControl {
    std::atomic<bool> paused{false};     // 是否暂停
    std::atomic<bool> cancelled{false};  // 是否取消
    std::mutex mtx;
    std::condition_variable cv;
};


// 最大用户名和密码长度
static const size_t MAX_FILEIDENTER_LEN = 33;
static const size_t MAX_ACCOUNT_LEN = 64;
static const size_t MAX_PASSWORD_LEN = 64;
static const size_t MAX_FILEDATA_LEN = 80;
static const size_t MAX_FILETYPE_LEN = 16;
static const size_t MAX_FILENAME_LEN = 256;
static const size_t MAX_MESSAGE_LEN = 256;

// 协议版本
static const uint16_t PROTOCOL_VERSION = 1;

// 数据回复
enum class MessageReturn: uint16_t {
    // 用户管理
    REGISTER_OK       = 0x0001,
    REGISTER_EXIST    = 0x0002,
    REGISTER_NO    = 0x0003,

    //登陆回复
    LOGIN_OK = 0x0004,
    LOGIN_NO = 0x0005,
    LOGIN_NOTEXIST = 0x0006,

    // 查询好友列表
    REFRESH_NO = 0x0007,
    REFRESH_OK = 0x0008,

    // 添加好友
    ADDFRIEND_NOTEXIST = 0x0009,
    ADDFRIEND_NOTAGREE = 0x000a,
    ADDFRIEND_AGREE = 0x000b,
    //删除好友
    DELETE_FRIEND_OK = 0x000e,
    DELETE_FRIEND_NO = 0x000f,

    //建立新文件夹
    NEW_DIR_OK = 0x0013,
    NEW_DIR_NO  = 0x0014,
    NEW_DIR_EXIST = 0x0015,

    //删除文件夹、文件
    DELETE_FILE_OK = 0x0016,
    DELETE_FILE_NO  = 0x0017,
    DELETE_FILE_NOTEXIST = 0x0018,

    //上传文件
    UPLOAD_FILE_OK = 0x1001,
    UPLOAD_FILE_NO = 0x1002,
    UPLOAD_FILE_PAUSE_OK = 0x1003,
    UPLOAD_FILE_PAUSE_NO = 0x1004,

    //分享文件
    SHARE_FILE_OK = 0x1005,
    SHARE_FILE_NO = 0x1006,
    SHARE_FILE_PAUSE_OK = 0x1007,
    SHARE_FILE_PAUSE_NO = 0x1008,

    // 心跳或其他
    HEARTBEAT      = 0xFFFF
};

// 消息类型枚举
enum class MessageType : uint16_t {
    // 用户管理
    REGISTER       = 0x0001,
    LOGIN          = 0x0002,
    LOGOUT         = 0x0003,
    REFRESH_FRIEND = 0x0004,

    ADD_FRIEND     = 0x0005,
    ADD_FRIEND_REQ = 0x0006,
    REMOVE_FRIEND  = 0x0007,
    REMOVE_FRIEND_REQ  = 0x0008,
    //发送消息
    SEND_FRIEND_MSG = 0x0011,
    //发送文件
    SEND_FRIEND_FILE = 0x0012,


    // 文件操作
    REFRESH_FILELIST = 0x1001,
    NEWFILEDIR = 0x1002,
    DELETEFILE = 0x1003,

    //上传文件
    UPLOADFILE = 0x1004,
    UPLOADFILE_FUNISH = 0x1005,
    UPLOADFILE_ACK = 0x1006,
    //下载文件
    DOWNFILE = 0x100b,
    DOWNFILE_ACK = 0x1007,
    DOWNFILE_PAUSE = 0x1008,
    DOWNFILE_CONTINUE = 0x1009,
    DOWNFILE_CANCEL = 0x100a,

//    //分享文件
//    SHAREFILE = 0x1008,
//    SHAREFILEPAUSE = 0x1009,
//    SHAREFILERE = 0x100a,

    // 心跳或其他
    HEARTBEAT      = 0xFFFF
};

// 数据包头部
#pragma pack(push, 1)
struct PacketHeader {
    uint16_t version;       // 协议版本
    MessageType type;          // 消息类型
    uint32_t length;        // 整个包的长度（字节数）
    uint64_t timestamp;     // 时间戳（毫秒）
    uint32_t session_id;    // 会话ID或对话ID
};
#pragma pack(pop)

// 用户信息结构体
#pragma pack(push, 1)
struct UserInfoMsg {
    char account[MAX_ACCOUNT_LEN];
    char friendName[MAX_ACCOUNT_LEN];
    char msg[MAX_MESSAGE_LEN];
};
#pragma pack(pop)

// 用户信息结构体
#pragma pack(push, 1)
struct UserInfo {
    char account[MAX_ACCOUNT_LEN];
    char userName[MAX_ACCOUNT_LEN];
    char password[MAX_PASSWORD_LEN];
    char email[MAX_ACCOUNT_LEN];

    char friendName[MAX_ACCOUNT_LEN];
    CloudDrive::MessageReturn type;
};
#pragma pack(pop)

// 数据包头部
#pragma pack(push, 1)
struct FriendInfo {
    int id;
    char name[MAX_ACCOUNT_LEN];
};
struct MesBack {
    CloudDrive::MessageReturn type;
    uint32_t firendCount;
    FriendInfo friends[64];
};
#pragma pack(pop)

// 数据包头部
// 回复文件列表
// 回复文件列表
#pragma pack(push, 1)
struct FileNumInfo {
    char fileName[MAX_FILENAME_LEN];
    char fileData[MAX_FILEDATA_LEN];
    char fileType[MAX_FILETYPE_LEN];

    uint32_t fileSize;
};
struct MesBackFile {
    CloudDrive::MessageReturn type;
    uint32_t FileNum;
    FileNumInfo fileInfo[64];
};
#pragma pack(pop)

// 通用数据包
struct Packet {
    PacketHeader header;
    std::vector<uint8_t> body; // body 保存 UserInfo、FileInfo 或 数据内容
};

// 辅助函数：获取当前时间戳（毫秒）
inline uint64_t now_millis() {
    using namespace std::chrono;
    return duration_cast<milliseconds>(
               system_clock::now().time_since_epoch()
               ).count();
}

// 序列化 Packet 到字节流
inline std::vector<uint8_t> serialize(const Packet& pkt) {
    std::vector<uint8_t> buffer;
    buffer.resize(sizeof(PacketHeader) + pkt.body.size());
    // 填充头部
    PacketHeader hdr = pkt.header;
    hdr.length = static_cast<uint32_t>(buffer.size());
    std::memcpy(buffer.data(), &hdr, sizeof(PacketHeader));
    // 填充 body
    if (!pkt.body.empty()) {
        std::memcpy(buffer.data() + sizeof(PacketHeader), pkt.body.data(), pkt.body.size());
    }
    return buffer;
}

// 反序列化字节流到 Packet
inline bool deserialize(const std::vector<uint8_t>& buffer, Packet& pkt) {
    if (buffer.size() < sizeof(PacketHeader)) return false;
    std::memcpy(&pkt.header, buffer.data(), sizeof(PacketHeader));
    if (buffer.size() != pkt.header.length) return false;
    pkt.body.resize(buffer.size() - sizeof(PacketHeader));
    if (!pkt.body.empty()) {
        std::memcpy(pkt.body.data(), buffer.data() + sizeof(PacketHeader), pkt.body.size());
    }
    return true;
}

// 构造用户请求包示例
inline CloudDrive::Packet makeUserPacket(
/*    CloudDrive::MessageType type, */      // 消息类型（REGISTER/LOGIN）
    CloudDrive::Packet pkt,
    const CloudDrive::UserInfo& uInfo,  // 用户信息
    uint32_t sessionId = 0               // 会话ID
    ) {
    pkt.header.session_id = sessionId;
    pkt.header.length = sizeof(CloudDrive::PacketHeader) + sizeof(CloudDrive::UserInfo);

    // 设置 body
    pkt.body.resize(sizeof(CloudDrive::UserInfo));
    std::memcpy(pkt.body.data(), &uInfo, sizeof(CloudDrive::UserInfo));

    return pkt;
}

// 构造用户请求包示例
inline CloudDrive::Packet makeUserMsgPacket(
    /*    CloudDrive::MessageType type, */      // 消息类型（REGISTER/LOGIN）
    CloudDrive::Packet pkt,
    const CloudDrive::UserInfoMsg& uInfo,  // 用户信息
    uint32_t sessionId = 0               // 会话ID
    ) {
    pkt.header.session_id = sessionId;
    pkt.header.length = sizeof(CloudDrive::PacketHeader) + sizeof(CloudDrive::UserInfoMsg);

    // 设置 body
    pkt.body.resize(sizeof(CloudDrive::UserInfoMsg));
    std::memcpy(pkt.body.data(), &uInfo, sizeof(CloudDrive::UserInfoMsg));
    return pkt;
}

// 构造回复包示例
inline CloudDrive::Packet makeRetPacket(
    CloudDrive::Packet pkt,
    const CloudDrive::MesBack & msg,  // 用户信息
    uint32_t sessionId = 0               // 会话ID
    ) {
    pkt.header.timestamp = now_millis();
    pkt.header.session_id = sessionId;
    pkt.header.length = sizeof(CloudDrive::PacketHeader) + sizeof(CloudDrive::MesBack);

    // 设置 body
    pkt.body.resize(sizeof(CloudDrive::MesBack));
    std::memcpy(pkt.body.data(), &msg, sizeof(CloudDrive::MesBack));
    return pkt;
}

// 构造文件列表回复
inline CloudDrive::Packet makePacket(
    MessageType type
    ) {
    CloudDrive::Packet pkt;
    pkt.header.type = type;
    pkt.header.timestamp = CloudDrive::now_millis();
    return pkt;
}


// 构造文件列表回复
inline CloudDrive::Packet makeRetFileListPacket(
    CloudDrive::Packet pkt,
    const CloudDrive::MesBackFile & msg,  // 用户信息
    uint32_t sessionId = 0               // 会话ID
    ) {
    pkt.header.session_id = sessionId;
    pkt.header.length = sizeof(CloudDrive::PacketHeader) + sizeof(CloudDrive::MesBackFile);

    // 设置 body
    pkt.body.resize(sizeof(CloudDrive::MesBackFile));
    std::memcpy(pkt.body.data(), &msg, sizeof(CloudDrive::MesBackFile));
    return pkt;
}

inline UserInfo makeUserInfo(std::string account,std::string userName,std::string password,std::string email,std::string friendName,MessageReturn type){
    UserInfo uIfo;
    std::memcpy(uIfo.account,account.c_str(),CloudDrive::MAX_ACCOUNT_LEN-1);
    std::memcpy(uIfo.userName,userName.c_str(),CloudDrive::MAX_ACCOUNT_LEN-1);
    std::memcpy(uIfo.password,password.c_str(),CloudDrive::MAX_ACCOUNT_LEN-1);
    std::memcpy(uIfo.email,email.c_str(),CloudDrive::MAX_ACCOUNT_LEN-1);
    std::memcpy(uIfo.friendName,friendName.c_str(),CloudDrive::MAX_ACCOUNT_LEN-1);
    uIfo.type = type;
    return uIfo;
}

// 文件信息结构体
#pragma pack(push, 1)
struct FileInfo {
    char filename[MAX_FILENAME_LEN];
    char filePath[MAX_MESSAGE_LEN];
    char sendName[MAX_ACCOUNT_LEN];
    char recName[MAX_ACCOUNT_LEN];
    char fileIdentfir[MAX_FILEIDENTER_LEN];
    uint64_t total_size;    // 文件实际大小
    uint64_t chunk_size;    // 本次发送的数据量
    uint64_t offset;        // 偏移位置
    uint32_t dataBlockId;
};
#pragma pack(pop)

// 文件信息结构体
#pragma pack(push, 1)
struct FileInfoSave {
    char filename[MAX_FILENAME_LEN];
    char filePath[MAX_MESSAGE_LEN];
    char sendName[MAX_ACCOUNT_LEN];
    char recName[MAX_ACCOUNT_LEN];
    char fileIdentfir[MAX_FILEIDENTER_LEN];
    uint64_t total_size;    // 文件实际大小
    uint64_t chunk_size;    // 本次发送的数据量
    uint64_t offset;        // 偏移位置
    uint32_t dataBlockId;
    std::chrono::time_point<std::chrono::steady_clock> dataTime;
    std::vector<uint8_t> data = {};
};
#pragma pack(pop)

// 构造用户请求包示例
inline CloudDrive::Packet makeFileInfoPacket(
    CloudDrive::Packet pkt,
    const CloudDrive::FileInfo& Fi,  // 用户信息
    uint32_t sessionId = 0               // 会话ID
    ) {
    pkt.header.session_id = sessionId;
    pkt.header.length = sizeof(CloudDrive::PacketHeader) + sizeof(CloudDrive::FileInfo);

    // 设置 body
    pkt.body.resize(sizeof(CloudDrive::FileInfo));
    std::memcpy(pkt.body.data(), &Fi, sizeof(CloudDrive::FileInfo));
    return pkt;
}
// 构造文件操作包示例
inline FileInfoSave makeFileDataSave(const std::string &sendName,const std::string &recName,const std::string& filename,const std::string& filePath,
                                     uint64_t totalSize, uint64_t chunkSize, uint64_t offset,uint32_t id,std::string fileIdenter,
                                     const std::vector<uint8_t>& data = {}){
    FileInfoSave fi;
    std::memset(&fi, 0, sizeof(fi));
    std::strncpy(fi.sendName,sendName.c_str(),MAX_ACCOUNT_LEN-1);
    std::strncpy(fi.recName,recName.c_str(),MAX_ACCOUNT_LEN-1);
    std::strncpy(fi.filename, filename.c_str(), MAX_FILENAME_LEN - 1);
    std::strncpy(fi.filePath, filePath.c_str(), MAX_MESSAGE_LEN - 1);
    std::strncpy(fi.fileIdentfir, fileIdenter.c_str(), MAX_FILEIDENTER_LEN-1);
    fi.total_size = totalSize;
    fi.chunk_size = chunkSize;
    fi.offset = offset;
    fi.dataBlockId = id;
    fi.dataTime = std::chrono::steady_clock::now();
    fi.data.resize(data.size());
    std::memcpy(fi.data.data(),data.data(),data.size());
    return fi;
}

// 构造文件操作包示例
inline Packet makeFilePacket(Packet pkt,const std::string &sendName,const std::string &recName, const std::string& filename,const std::string& filePath,
                             uint64_t totalSize, uint64_t chunkSize, uint64_t offset,uint32_t id, std::string fileIdenter,
                             const std::vector<uint8_t>& data = {},uint32_t session = 0) {

    FileInfo fi;
    std::memset(&fi, 0, sizeof(fi));
    std::strncpy(fi.sendName,sendName.c_str(),MAX_ACCOUNT_LEN-1);
    std::strncpy(fi.recName,recName.c_str(),MAX_ACCOUNT_LEN-1);
    std::strncpy(fi.filename, filename.c_str(), MAX_FILENAME_LEN - 1);
    std::strncpy(fi.filePath, filePath.c_str(), MAX_MESSAGE_LEN - 1);
    std::strncpy(fi.fileIdentfir, fileIdenter.c_str(), MAX_FILEIDENTER_LEN-1);
    fi.total_size = totalSize;
    fi.chunk_size = chunkSize;
    fi.offset = offset;
    fi.dataBlockId = id;


    // 组合 body: FileInfo + 可能的数据块
    pkt.body.resize(sizeof(FileInfo) + data.size());
    pkt.header.session_id = session;
    std::memcpy(pkt.body.data(), &fi, sizeof(FileInfo));
    if (!data.empty()) {
        std::memcpy(pkt.body.data() + sizeof(FileInfo), data.data(), data.size());
    }
    pkt.header.length = sizeof(PacketHeader) + pkt.body.size();
    return pkt;
}
} // namespace CloudDrive
